﻿using ArtMath.Flag.Helper;
using ArtMath.Resource;
using Microsoft.Win32;
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Security.AccessControl;
using System.Security.Principal;
using System.Windows.Forms;

namespace ArtMath.Flag
{
    public static class Flags
    {
        [DllImport("user32.dll", EntryPoint = "ShowCursor", CharSet = CharSet.Auto)]
        static extern void ShowCursor(int status);
        public static bool Shift, Ctrl, Alt, PasteObjectEnabled, PasteStyleEnabled, SaveLayoutBeforeExit = true;
        public static bool ASCsuccess { get; private set; }
        public const string SoftwareName = "ArtMath", DocumentExtension = ".pad", RelationKeyName = "PAD_FileType",
            OfficialIP = "47.103.48.111", FeedbackReceiver = "liaodong1997@126.com", OfficialWebsite = "http://" + OfficialIP, 
            ExceptionShieldMessage = "0", TempDocumentSuffix = ".temp" + DocumentExtension;
        public const int WM_COPYDATA = 0x004A;
        public static readonly string
            DesktopPath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory),
            DefaultLayoutPath = Application.StartupPath + "\\dockpanel.config",
            DocumentIconPath = Application.StartupPath + "\\document.ico",
            LayoutDirectoryPath = Application.StartupPath + "\\layouts",
            UpdateDirectoryPath = Application.StartupPath + "\\update",
            TempPath = Path.GetTempPath(),
            AdministratorFlag;
        static bool cursorVisible = true;
        public static bool CursorVisible
        {
            get { return cursorVisible; }
            set
            {
                if (cursorVisible == value) return;
                cursorVisible = value;
                ShowCursor(cursorVisible ? 1 : 0);
            }
        }
        public static bool HighPerformanceTimerEnabled
        {
            get { return Stopwatch.IsHighResolution; }
        }
        static Flags()
        {
            WindowsIdentity current = WindowsIdentity.GetCurrent();
            WindowsPrincipal prin = new WindowsPrincipal(current);
            if (prin.IsInRole(WindowsBuiltInRole.Administrator))
            {
                AdministratorFlag = Resources.LeftParenthesis + Resources.Translate("Administrator") + Resources.RightParenthesis;
            }
            else
            {
                AdministratorFlag = string.Empty;
            }
            if (!HighPerformanceTimerEnabled)
            {
                MessageBox.Show(Resources.Translate("FailedEnableHighPerformanceTimer"), Resources.Translate("Exclamation"), MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
        }
        public static void DeleteTemporaryFiles(bool ignoreException = false)
        {
            try
            {
                DirectoryInfo di = new DirectoryInfo(TempPath);
                foreach (FileInfo fi in di.GetFiles("*" + TempDocumentSuffix, SearchOption.TopDirectoryOnly))
                {
                    fi.Delete();
                }
            }
            catch (Exception ex)
            {
                if (!ignoreException)
                {
                    MessageBox.Show(ex.Message, Resources.Translate("Error"), MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }
        public static void RegisterExtension()
        {
            RegistryKey extKey = Registry.ClassesRoot.CreateSubKey(DocumentExtension, RegistryKeyPermissionCheck.ReadWriteSubTree);
            extKey.SetValue("", RelationKeyName);
            extKey.Close();

            RegistryKey relationKey = Registry.ClassesRoot.CreateSubKey(RelationKeyName, RegistryKeyPermissionCheck.ReadWriteSubTree);
            relationKey.SetValue("", SoftwareName + Resources.Join + Resources.Translate("Document"));

            RegistryKey iconKey = relationKey.CreateSubKey("DefaultIcon", RegistryKeyPermissionCheck.ReadWriteSubTree);
            iconKey.SetValue("", DocumentIconPath);

            RegistryKey shellKey = relationKey.CreateSubKey("Shell", RegistryKeyPermissionCheck.ReadWriteSubTree),
                openKey = shellKey.CreateSubKey("Open", RegistryKeyPermissionCheck.ReadWriteSubTree),
                cmdKey = openKey.CreateSubKey("Command", RegistryKeyPermissionCheck.ReadWriteSubTree);
            cmdKey.SetValue("", $"{Application.StartupPath}\\ArtMath.Window.exe %1");
            relationKey.Close();
        }
        public static string GetExtensionExecutablePath()
        {
            RegistryKey relationKey = Registry.ClassesRoot.OpenSubKey(RelationKeyName, RegistryKeyPermissionCheck.ReadSubTree, RegistryRights.ReadKey),
                cmdKey = relationKey.OpenSubKey("Shell", RegistryKeyPermissionCheck.ReadSubTree, RegistryRights.ReadKey).
                OpenSubKey("Open", RegistryKeyPermissionCheck.ReadSubTree, RegistryRights.ReadKey).
                OpenSubKey("Command", RegistryKeyPermissionCheck.ReadSubTree, RegistryRights.ReadKey);
            string tmp = cmdKey.GetValue("").ToString();
            if (tmp == null || tmp.Length < 3)
            {
                return string.Empty;
            }
            return tmp.Substring(0, tmp.Length - 3);
        }
        public static bool GetExtensionRegistered()
        {
            return Registry.ClassesRoot.OpenSubKey(DocumentExtension, RegistryKeyPermissionCheck.ReadSubTree, RegistryRights.ReadKey) != null;
        }
        public static void EnableHotKey()
        {
            HotKey.KeyDownEvent += KeyDown;
            HotKey.KeyUpEvent += KeyUp;
            ASCsuccess = HotKey.Start();
            if (!ASCsuccess)
            {
                MessageBox.Show(string.Format(Resources.Translate("FailedEnableHotKey"), "Ctrl, Shift, Alt"), Resources.Translate("Error"), MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
        }
        public static void DisableHotKey()
        {
            ASCsuccess = HotKey.Stop();
            if (!ASCsuccess)
            {
                MessageBox.Show(string.Format(Resources.Translate("FailedDisableHotKey"), "Ctrl, Shift, Alt"), Resources.Translate("Error"), MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        static void KeyDown(Keys key)
        {
            switch (key)
            {
                case Keys.Control:
                case Keys.ControlKey:
                case Keys.LControlKey:
                case Keys.RControlKey:
                    Ctrl = true;
                    break;
                case Keys.Shift:
                case Keys.ShiftKey:
                case Keys.LShiftKey:
                case Keys.RShiftKey:
                    Shift = true;
                    break;
                case Keys.Alt:
                    Alt = true;
                    break;
            }
        }
        static void KeyUp(Keys key)
        {
            switch (key)
            {
                case Keys.Control:
                case Keys.ControlKey:
                case Keys.LControlKey:
                case Keys.RControlKey:
                    Ctrl = false;
                    break;
                case Keys.Shift:
                case Keys.ShiftKey:
                case Keys.LShiftKey:
                case Keys.RShiftKey:
                    Shift = false;
                    break;
                case Keys.Alt:
                    Alt = false;
                    break;
            }
        }
        public static void ShieldCtrl(Action act)
        {
            if (act == null) return;
            bool bkp = Ctrl;
            Ctrl = false;
            act();
            Ctrl = bkp;
        }
        public static void UseCtrl(Action act)
        {
            if (act == null) return;
            bool bkp = Ctrl;
            Ctrl = true;
            act();
            Ctrl = bkp;
        }
    }
}
